package com.wsfPro.util.jwt;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;

@Component
public final class JwtUtil {
  private final Logger log = LoggerFactory.getLogger(JwtUtil.class);
  @Autowired private RedisTemplate redisTemplate;
  @Autowired private JwttokenconfigBean jwttokenconfigBean;

  public String getJwtTokenByRequestHeader(HttpServletRequest request){
    String jwtToken=null;
    String authHeader = request.getHeader(this.getJwttokenconfigBean().getHeader());
    //            request.getHeader(jwtUtil.getJwttokenconfigBean().getHeader());

    if (authHeader != null
            && authHeader.startsWith(this.getJwttokenconfigBean().getTokenHead())) {
      // 通过token自带的信息生成登录实体username password roles
      // 如果验证token如果成功则存入SecurityContextHolder上下文供后面url资源权限认证
      jwtToken=
              authHeader.substring(this.getJwttokenconfigBean().getTokenHead().length());
    }
   return jwtToken;
  }

  public void addJwtTokenToRedisHash(String jwtJti,String jwtToken) {
    redisTemplate.opsForHash().put(JwttokenconfigEnum.jwtTokenHash.getValue(), jwtJti,jwtToken);
// redisTemplate.expire只对顶级key起作用，不对具体的某个集合的某个属性key起作用
//    redisTemplate.expire(JwttokenconfigEnum.jwtTokenHash.getValue(),jwttokenconfigBean.getEffectiveTime(),TimeUnit.MILLISECONDS);
    //    log.info();
    log.info("redisHash addJwtToken:" + jwtToken);
  }

  public boolean isHasJwtTokenByRedisHash(String jwtJti) {
    return redisTemplate.opsForHash().hasKey(JwttokenconfigEnum.jwtTokenHash.getValue(), jwtJti);
  }
  public String getJwtTokenByRedisHash(String jwtJti) {
    Object resJwtToken =redisTemplate.opsForHash().get(JwttokenconfigEnum.jwtTokenHash.getValue(), jwtJti);
    if(resJwtToken!=null){
    return resJwtToken.toString();
    }
    return null;
  }
  public boolean removeJwtTokenByRedisHash(String jwtJti) {
    boolean res = true;
    long number = redisTemplate.opsForHash().delete(JwttokenconfigEnum.jwtTokenHash.getValue(), jwtJti);
    if (number != 1) {
      res = false;
    }
    log.info("redisSet removeJwtToken number:" + number);
    return res;
  }
  //    /**
  //     * 解析jwt
  //     */
  //    public Claims parseJWT(String jsonWebToken, String base64Security) {
  //        try {
  //
  //            Claims claims = Jwts.parser()
  //                    .setSigningKey(signingKey)
  //                    .parseClaimsJws(jsonWebToken).getBody();
  //            return claims;
  //        } catch (Exception ex) {
  //            return null;
  //        }
  //    }

  //    /**
  //     * 构建jwt
  //     */
  //    public String createJWT(
  //            String name,
  //            String userId,
  //            String role,
  //            String audience,
  //            String issuer,
  //            long TTLMillis,
  //            String base64Security) {
  //        long nowMillis = System.currentTimeMillis();
  //        Date now = new Date(nowMillis);
  //        // 生成签名密钥
  //        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
  //        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(base64Security);
  //        signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
  //
  //        // 添加构成JWT的参数
  //        JwtBuilder builder =
  //                Jwts.builder()
  //                        .setHeaderParam("typ", "JWT")
  //                        .claim("role", role)
  //                        .claim("unique_name", name)
  //                        .claim("userid", userId)
  //                        .setIssuer(issuer)
  //                        .setAudience(audience)
  //                        .signWith(signatureAlgorithm, signingKey);
  //        // 添加Token过期时间
  //        if (TTLMillis >= 0) {
  //            long expMillis = nowMillis + TTLMillis;
  //            Date exp = new Date(expMillis);
  //            builder.setExpiration(exp).setNotBefore(now);
  //        }
  //
  //    // 生成JWT
  //        return builder.compact();
  // }

  // 生成签名密钥
  //    byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(audience.getBase64Secret());
  //    Key signingKey = new SecretKeySpec(apiKeySecretBytes,
  // SignatureAlgorithm.HS512.getJcaName());

  // you can put any data in the map
  public String generateToken(Map<String, Object> paramMap) {
    // 1000 hour
    // 签发时间
    Date iat = Calendar.getInstance().getTime();
    log.info("generateToken签发时间iat:" + iat.getTime());
    long effectiveTime = jwttokenconfigBean.getEffectiveTime();
    log.info("generateToken有效期effectiveTimeLong:" + effectiveTime);
    long expLong = iat.getTime() + effectiveTime;
    log.info("generateToken过期时间expLong:" + expLong);
    // 过期时间
    Date exp = new Date(expLong);
    paramMap.put(JwttokenconfigEnum.createDate.getValue(), iat.getTime());
    String jwt =
        Jwts.builder()
            .setHeaderParam(JwttokenconfigEnum.type.getValue(), JwttokenconfigEnum.JWT.getValue())
            .setClaims(paramMap)
            .setIssuedAt(iat)
            .setExpiration(exp)
            .setNotBefore(iat)
            .setIssuer(jwttokenconfigBean.getIss())
            .signWith(SignatureAlgorithm.HS512, jwttokenconfigBean.getBase64Secret())
            .compact();
    return jwt;
  }

  /**
   * 解析token时间是去从毫秒为单位变为以秒为单位
   *
   * @param token
   * @return
   */
  public Map<String, Object> validateToken(String token) {
    // parse the token.生成签名密钥
    Map<String, Object> body =
        Jwts.parser()
            .setSigningKey(jwttokenconfigBean.getBase64Secret())
            .parseClaimsJws(token)
            .getBody();
    return body;
  }

  /**
   * 自定义createDate能获取到当前的创建时间 利用exp过期时间-iat签发时间得到有效期时间+自定义createDate<当前时间则过期 如果大于
   * 则是否大于20,再过20秒就过期是的话刷新towken
   *
   * @param map 验证后的towkenMap
   * @return
   */
  public String refreshToken(Map map) {

    long createDateLong =
        Long.parseLong(map.get(JwttokenconfigEnum.createDate.getValue()).toString());
    log.info("refreshToke创建时间：" + createDateLong);
    long nowTime = System.currentTimeMillis();
    long timeLeft = jwttokenconfigBean.getEffectiveTime() + createDateLong - nowTime;
    log.info("jwtToken 剩余刷新时间timeLeft：" + timeLeft);
//    如果验证通过的情况下
    if (timeLeft < jwttokenconfigBean.getRefreshTime() && timeLeft > 0) {
      return generateToken(map);
    }
    return null;
  }

  public JwttokenconfigBean getJwttokenconfigBean() {
    return jwttokenconfigBean;
  }
}
